package com.slofzx.nuoda.evaluation.steretype;

import com.slofzx.nuoda.common.util.ReflectionsUtil;
import com.slofzx.nuoda.init.AbstractServiceLoader;
import org.reflections.Reflections;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 模型计算结果导出关联项
 */
@Component
public class ExcelExportItemLoader extends AbstractServiceLoader {

    private List<ExcelExportItem> dataList = new ArrayList<>();

    public List<ExcelExportItem> getDataList() {
        return dataList;
    }

    protected void init() {
        Reflections reflections = ReflectionsUtil.getReflections("com.slofzx.nuoda");
        //获取需要导出数据的类
        Set<Class<?>> configSet = reflections.getTypesAnnotatedWith(ExcelExportConfig.class);
        if (configSet == null) {
            return;
        }
        //记录字段集合，id不允许重复
        Map<String,Field> fieldMap = new HashMap<>();
        for (Class<?> clz : configSet) {
            ExcelExportConfig excelExportConfig = clz.getAnnotation(ExcelExportConfig.class);
            if(excelExportConfig == null) {
                continue;
            }
            List<Field> fieldList = ReflectionsUtil.getAllAccessibleFields(clz);
            if (fieldList == null) {
                continue;
            }
            for (Field field : fieldList) {
                ExcelExportItemConfig itemConfig = field.getAnnotation(ExcelExportItemConfig.class);
                if (itemConfig == null) {
                    continue;
                }
                Field conflictField = fieldMap.get(itemConfig.id());
                if(conflictField!=null) {
                    logger.error("Excel导出指标存在重复id,{}::{} <--> {}::{}",field.getDeclaringClass(),field.getName(),conflictField.getDeclaringClass(),conflictField.getName());
                    throw new RuntimeException("Excel导出指标存在重复id: "+ itemConfig.id());
                }
                fieldMap.put(itemConfig.id(),field);
                try {
                    ExcelExportItem item = new ExcelExportItem() {

                        @Override
                        public String getGroup() {
                            return excelExportConfig.name();
                        }

                        @Override
                        public boolean isYearRelated() {
                            return excelExportConfig.yearRelated();
                        }


                        @Override
                        public Object getValue(Object target) {
                            Object result = null;
                            if(target == null) {
                                return null;
                            }
                            try {
                                result = ReflectionsUtil.invokeGetter(target, field.getName());
                            } catch (Exception e) {
                                logger.error(this.getClass().getName()+" 获取数据项值失败,{}:{}", target,field.getName());
                            }
                            return result;
                        }

                        @Override
                        public String getId() {
                            return itemConfig.id();
                        }

                        @Override
                        public String getName() {
                            return isYearRelated()?itemConfig.name()+"(年份相关)":itemConfig.name();
                        }
                    };
                    dataList.add(item);
                } catch (Exception e) {
                    logger.error("初始化评价结果导出项失败,{}", itemConfig, e);
                }
            }
        }
    }
}
